package com.cn.icss.service.impl;

import com.cn.icss.service.IDictionaryTypeService;
import com.cn.icss.service.IStreamService;
import com.cn.icss.vo.Dictionary;
import com.cn.icss.vo.StreamInfo;
import com.cn.icss.vo.StreamtypeInfo;
import com.jfinal.aop.Aop;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.IAtom;
import com.jfinal.plugin.redis.Cache;
import com.jfinal.plugin.redis.Redis;
import com.twmacinta.util.MD5;

import java.sql.SQLException;
import java.util.*;

/**
 * @中软华腾软件系统有限公司,未经授权不得擅自传播
 * @类描述:
 * @类名称:StreamServiceImpl
 * @作者: Administrator
 * @编辑时间: 2020/04/09 09:33
 * @版本: 1.0
 */
public class StreamServiceImpl implements IStreamService {

    StreamInfo streamInfoDao = new StreamInfo().dao();
    StreamtypeInfo streamtypeInfoDao = new StreamtypeInfo().dao();
    // 设置好redis连接模块
    Cache userCache = Redis.use("liveStream");
    /**
    *@中软华腾软件系统有限公司,未经授权不得擅自传播
    *@方法描述: 查询流的基本信息
    *@方法参数描述:
    ** @param streamId
    *@作者: 蒋正午
    *@编辑时间: 2020/04/20  11:00
    *@返回值描述: com.cn.icss.vo.StreamInfo
    */
    @Override
    public StreamInfo findBaseStreamInfo(String streamId) {
        // 首先关联查询出
        List<StreamInfo> streamInfos = streamInfoDao.find("SELECT info.*  FROM `stream_info` info WHERE info.streamid= ?", streamId);
        if(streamInfos==null || streamInfos.size()==0){
            throw new RuntimeException("输入的streamId不存在!");
        }
        return streamInfos.get(0);
    }

    /**
    *@中软华腾软件系统有限公司,未经授权不得擅自传播
    *@方法描述: 查询所有的流信息
    *@方法参数描述:
    ** @param streamId
    *@作者: 蒋正午
    *@编辑时间: 2020/04/20  10:59
    *@返回值描述: java.util.Map<java.lang.String,java.lang.Object>
    */
    @Override
    public Map<String, Object> findStreamInfo(String streamId) {
        Map<String,Object> streamInfo = new HashMap<>();
        // 1.查询基本信息
        StreamInfo baseStreamInfo = this.findBaseStreamInfo(streamId);
        if(baseStreamInfo!=null){
            // 放入基本信息
            streamInfo.put("baseInfo", baseStreamInfo);
        }
        // 2. 查询Redis中的流状态和当前在线人数
        String key = "streamInfo_" + streamId;
        streamInfo.put("streamId", streamId);
        streamInfo.put("streamstatus",userCache.hget(key,"status")==null?"OFF":userCache.hget(key,"status"));
        streamInfo.put("num",userCache.hget(key,"num")==null? 0:userCache.hget(key,"num"));
        // 查询其他的信息
        return streamInfo;
    }

    /**
    *@中软华腾软件系统有限公司,未经授权不得擅自传播
    *@方法描述:
    *@方法参数描述: 目前只持支一个房间一路推流
    ** @param streamId
     * @param tokenId
    *@作者: 蒋正午
    *@编辑时间: 2020/04/17  10:20
    *@返回值描述: java.util.Map<java.lang.String,java.lang.Object>
    */
    @Override
    public Map<String, Object> findStreamAddr(String streamId, String tokenId) {
        // 1. 通过流查询StreamKey 2. 查询流对应的房间和类型 3.类型递归查询全部 4. 拼装成地址
        Map<String,Object> dataMap = new HashMap<>();
        StreamInfo streamInfo = this.findBaseStreamInfo(streamId);
        String streamKey = streamInfo.getStreamKey();
        List<StreamtypeInfo> streamtypeInfos = streamtypeInfoDao.find("SELECT dic.dicid,dic.dicType FROM `streamtype_info` typeinfo,`dictionary` dic WHERE typeinfo.dicid=dic.dicid AND typeinfo.streamid= ? ", streamId);
        if(streamtypeInfos!=null && streamtypeInfos.size()>0){
            dataMap.put("streamKey", streamKey);
            IDictionaryTypeService dictionaryTypeService = Aop.get(DictionaryTypeServiceImpl.class);
            Map<String,Object> typePath = dictionaryTypeService.finddicTpyePath(streamtypeInfos.get(0));
            //  组装url地址
            StringBuffer sb_push = new StringBuffer();
            StringBuffer sb_play = new StringBuffer();
            Prop prop = PropKit.use("streamcontext.txt");
            String PUSHIP = prop.get("PUSHIP");
            String PUSHPORT = prop.get("PUSHPORT");
            String PLAYIP = prop.get("PLAYIP");
            String PLAYPORT = prop.get("PLAYPORT");
            sb_push.append("rtmp://").append(PUSHIP+":").append(PUSHPORT);
            sb_play.append("rtmp://").append(PLAYIP+":").append(PLAYPORT);
            for(Map.Entry<String,Object> entry:typePath.entrySet()){
                List<String> typesIds = (List<String>) entry.getValue();
                for(int i=typesIds.size()-1;i>=0;i--){
                    sb_push.append("/"+typesIds.get(i));
                    sb_play.append("/"+typesIds.get(i));
                }
                // 继续拼接dicid
                sb_push.append("/"+entry.getKey()).append("/"+streamId);
                sb_play.append("/"+entry.getKey()).append("/"+streamId);
            }
            dataMap.put("pubAddr",sb_push.toString());
            dataMap.put("playAddr", sb_play.toString());
            // 最后要把登录的信息放入Redis
            //userCache.set(tokenId, "sessionId:"+tokenId);
        }
        return dataMap;
    }


    @Override
    public Map<String, Object> createStream(String roomTypeId,String dicId) {

        Map<String,Object> result = new HashMap<>();
        // 注意操作的单一职责原则
        Db.tx(() -> {
            boolean flag = false;
            String _dicId = dicId;
            try {
                String streamId = "zr" + UUID.randomUUID().toString().replaceAll("-", "");
                MD5 md5 = new MD5();
                md5.Update(_dicId,"UTF-8");
                _dicId= md5.asHex();
                boolean isSaveStreamInfo = this.saveStreamInfo(streamId);
                boolean isSaveDictionary = this.saveDictionary(_dicId, roomTypeId);
                boolean isSaveStreamTypeInfo = this.saveStreamTypeInfo(streamId,_dicId);
                if(isSaveStreamInfo && isSaveDictionary && isSaveStreamTypeInfo){
                    result.put("streamId", streamId);
                    // 再去生成播流与推流的地址
                    Map<String, Object> streamAddrMap = this.findStreamAddr(streamId, "");
                    result.put("playAddr",streamAddrMap.get("playAddr"));
                    result.put("pushAddr", streamAddrMap.get("pubAddr"));
                    result.put("streamId", streamId);
                    flag = true;
                }else{
                    flag = false;
                }
            } catch (Exception e) {
                e.printStackTrace();
                flag = false;
            }
            return flag;
        });


        return result;
    }

    // 更新流信息
    @Override
    public Map<String, Object> updateStream(String streamId, String roomTypeId, String newdicId) {

         Map<String,Object> result = null;
         // 查出之前的旧数据
        StreamtypeInfo streamTypeInfo = streamtypeInfoDao.findFirst("SELECT type_info.*  FROM `streamtype_info`  type_info WHERE type_info.streamid= ?", streamId);
        if(streamTypeInfo!=null){
            String oldDicid = streamTypeInfo.getDicid();
            // 先删旧数据然后插入新数据
            boolean succeed = this.deleteStreamRelative(streamId,oldDicid);
            if(succeed){
                result = createStream(roomTypeId,newdicId);
            }
        }

        return result;
    }

    public  boolean deleteStreamRelative(String streamId,String oldDicid){

        boolean succeed = Db.tx(new IAtom(){

            public boolean run() throws SQLException {
                int count =Db.update("delete from streamtype_info where dicid = ? AND streamid=?  ", oldDicid, streamId);
                int count2 = Db.update("delete from stream_info where streamid = ? ", streamId);
//                int count3 = Db.update("delete from dictionary where dicid = ? ", oldDicid);
                return count == 1 && count2 == 1 ;
            }});
        return succeed;
    }


    // 保存StreamInfo
    protected boolean saveStreamInfo(String streamId){
        StreamInfo streamInfo = new StreamInfo();
        streamInfo.setId(UUID.randomUUID().toString());
        streamInfo.setStreamid(streamId);
        streamInfo.setStreamKey("zrht");
        streamInfo.setCreateTime(new Date());
        streamInfo.setUpdateTime(new Date());
        // 先保存streamInfo
        boolean result = streamInfo.save();
        return result;
    }

    // 保存字典
    protected boolean saveDictionary(String dicId,String roomTypeId){

        boolean result = false;
        try {
            Dictionary dictionaryDao = new Dictionary().dao();
            Dictionary first = dictionaryDao.findFirst("SELECT dicid,dicType FROM dictionary WHERE dicid = ?  AND dicType=? ", dicId,roomTypeId);
            if(first!=null && first.getDicid()!=null && first.getDicid().length()>0){
                // 已经存在了不用保存字典了
                return true;
            }
            Dictionary dictionary = new Dictionary();
            dictionary.setId(UUID.randomUUID().toString());
            dictionary.setDicid(dicId);
            dictionary.setDicType(roomTypeId);
            dictionary.setDicContent("直播房间");
            result = dictionary.save();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    // 保存字典关系表(流关系表)
    protected boolean saveStreamTypeInfo(String streamId,String dicId){
        StreamtypeInfo streamtypeInfo = new StreamtypeInfo();
        streamtypeInfo.setId(UUID.randomUUID().toString());
        streamtypeInfo.setStreamid(streamId);
        streamtypeInfo.setDicid(dicId);
        streamtypeInfo.setCreateTime(new Date());
        streamtypeInfo.setUpdateTime(new Date());
        return  streamtypeInfo.save();
    }




}
